package com.butterfly.encrypt.msg;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;

import com.butterfly.encrypt.util.Des;
import com.butterfly.encrypt.util.Sign;
import com.butterfly.encrypt.util.Tools;
import com.sun.org.apache.xml.internal.security.utils.Base64;

/**
 * 信息转换类
 * 主要是对信息加密解密的操作
 * @author fox email:hitman__47@163.com
 * @version 1.0 2013-10-30
 *
 */
public class MsgConvertor {
	private static final  Logger log = Logger.getLogger(MsgConvertor.class);
	/**
	 *  将指定内容用  蝴蝶加解密系统 的加密流程进行加密，返回加密后的结果
	 *  步骤：
	 *  	1 将信息进行Document化
	 *  	2 对结果进行序列化后加签,并对加签结果进行base64编码
	 *  	3 Docuemnt的对象增加SIGN子节点，对将加签结果放入该节点中
	 *  	4 取出DES主密钥
	 *  	5 对增加了节点的Docuemnt对象进行DES加密
	 *  	6 对DES加密结构进行base64加密后返回
	 * @param msg
	 * 			 需要加密的内容
	 * @param desKey
	 * 			DES密钥
	 * @param prikey
	 * 			私钥
	 * @return
	 * 			返回加密结果
	 * @throws IOException 
	 * @throws JDOMException 
	 * @throws BadPaddingException 
	 * @throws IllegalBlockSizeException 
	 * @throws NoSuchPaddingException 
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeyException 
	 */
	public static String encyptBody(String msg,byte[] desKey,RSAPrivateKey prikey) throws JDOMException, IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{
		//1 将信息进行Document化
		Document document = Tools.getXmlDoc(msg.getBytes());
		//2 对结果进行序列化后加签,并对加签结果进行base64编码
		byte[] rsa1= Sign.sign(Tools.toByteArrays(document), prikey);
		String sign=new String(Base64.encode(rsa1));
		//3 Docuemnt的对象增加SIGN子节点，对将加签结果放入该节点中
		Element element = new Element("SIGN");
		element.setText(sign);
		document.getRootElement().addContent(element);
		String signResult=new String(Tools.toByteArrays(document));
		//4 取出DES主密钥 5 对增加了节点的Docuemnt对象进行DES加密
		byte[] ens=Des.encryptDes(signResult.getBytes(), desKey);
		//6 对DES加密结构进行base64加密后返回
		String ensBase64=Base64.encode(ens);
		log.info(String.format("加密前的数据[%s]加密后的数据[%s]",signResult,ensBase64));
		return ensBase64;
	}
	/**
	 * 将 蝴蝶 加解密系统 返回内容进行解密，返回解密后的结果，如果验签不过，报异常
	 * 步骤：
	 * 		1 取出DES主密钥。
	 * 		2 对信息进行base64 解码
	 * 		3 对解码结果进行DES解密
	 * 		4 对DES解密结果进行验签，如果验签失败，返回异常
	 * 		5 返回最终解密结果
	 * @param msg
	 * 				 蝴蝶 加解密系统 返回内容
	 * @param desKey
	 * 				DES密钥
	 * @param pubKey
	 * 				 公钥    
	 * @return
	 * 			返回解密结果
	 * @throws Exception 
	 * @throws SignatureException 
	 */
	public static String decryptBody(String msg,byte[] desKey,RSAPublicKey pubKey) throws SignatureException, Exception{
		//1 取出DES主密钥。2 对信息进行base64 解码3 对解码结果进行DES解密
		byte[] des = Des.decryptDes(Base64.decode(msg), desKey);
		String body=new String (des,"UTF-8");
		
		Document document=Tools.getXmlDoc(body.getBytes());
		//4 对DES解密结果进行验签，如果验签失败，返回异常
		String signstr=document.getRootElement().getChildTextTrim("SIGN");
		if(!Sign.verifySign(body.getBytes(), document, signstr, pubKey))
			throw new Exception("报文体验签失败！");
		return body;
			
			
	}
}
